import type { App, DirectiveBinding } from 'vue';
import { Local } from '/@/units/Store'
import { Debounce } from '/@/units/debusg'

// import loadingimg from '@/assets/images/2021090708410877.gif'
export default function DOMFdirective(app: App) {
    // DOM自定义指令1 
    //    图片懒加载
    app.directive('lazyload', (el: any, binding: DirectiveBinding<any>) => {
        // console.log(el.dataset);
        // 是否需要懒加载
        const { nolazy } = binding.value
        if (nolazy) return el.src = el.dataset.src
        // 懒加载暂时没有显示出来的图片，显示正在加载中的图片
        const placeload = 'loadingimg'
        el.src = placeload
        // 判断目标是否出现在可视化上面
        const obServer = new IntersectionObserver(entries => {
            // 如果intersectionRatio 为0 ，则目标在视野外
            //我们不做任何事情
            if (entries[0].intersectionRatio <= 0) return;
            el.src = el.dataset.src
            obServer.unobserve(el)
        })
        obServer.observe(el)
    })

    /**
     * 拖动指令
     */
    app.directive('drag', {
        mounted(el, binding: DirectiveBinding<any>) {
            if (!binding.value) return false;

            // 父盒子拖动的标签
            const dragDom = document.querySelector(binding.value[0]) as HTMLElement;
            // 需要拖动的标签
            const dragHeader = document.querySelector(binding.value[1]) as HTMLElement;

            dragHeader.onmouseover = () => (dragHeader.style.cursor = `move`);

            function down(e: any, type: string) {
                // 鼠标按下，计算当前元素距离可视区的距离
                const disX = type === 'pc' ? e.clientX - dragHeader.offsetLeft : e.touches[0].clientX - dragHeader.offsetLeft;
                const disY = type === 'pc' ? e.clientY - dragHeader.offsetTop : e.touches[0].clientY - dragHeader.offsetTop;

                // body当前宽度
                const screenWidth = document.body.clientWidth;
                // 可见区域高度(应为body高度，可某些环境下无法获取)
                const screenHeight = document.documentElement.clientHeight;

                // 对话框宽度
                const dragDomWidth = dragDom.offsetWidth;
                // 对话框高度
                const dragDomheight = dragDom.offsetHeight;

                const minDragDomLeft = dragDom.offsetLeft;
                const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;

                const minDragDomTop = dragDom.offsetTop;
                const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight;

                // 获取到的值带px 正则匹配替换
                let styL: any = getComputedStyle(dragDom).left;
                let styT: any = getComputedStyle(dragDom).top;

                // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
                if (styL.includes('%')) {
                    styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100);
                    styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100);
                } else {
                    styL = +styL.replace(/\px/g, '');
                    styT = +styT.replace(/\px/g, '');
                }

                return {
                    disX,
                    disY,
                    minDragDomLeft,
                    maxDragDomLeft,
                    minDragDomTop,
                    maxDragDomTop,
                    styL,
                    styT,
                };
            }

            function move(e: any, type: string, obj: any) {
                let { disX, disY, minDragDomLeft, maxDragDomLeft, minDragDomTop, maxDragDomTop, styL, styT } = obj;

                // 通过事件委托，计算移动的距离
                let left = type === 'pc' ? e.clientX - disX : e.touches[0].clientX - disX;
                let top = type === 'pc' ? e.clientY - disY : e.touches[0].clientY - disY;

                // 边界处理
                if (-left > minDragDomLeft) {
                    left = -minDragDomLeft;
                } else if (left > maxDragDomLeft) {
                    left = maxDragDomLeft;
                }

                if (-top > minDragDomTop) {
                    top = -minDragDomTop;
                } else if (top > maxDragDomTop) {
                    top = maxDragDomTop;
                }

                // 移动当前元素
                dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
            }

            /**
             * pc端
             * onmousedown 鼠标按下触发事件
             * onmousemove 鼠标按下时持续触发事件
             * onmouseup 鼠标抬起触发事件
             */
            dragHeader.onmousedown = (e) => {
                const obj = down(e, 'pc');
                document.onmousemove = (e) => {
                    move(e, 'pc', obj);
                };
                document.onmouseup = () => {
                    document.onmousemove = null;
                    document.onmouseup = null;
                };
            };

            /**
             * 移动端
             * ontouchstart 当按下手指时，触发ontouchstart
             * ontouchmove 当移动手指时，触发ontouchmove
             * ontouchend 当移走手指时，触发ontouchend
             */
            dragHeader.ontouchstart = (e) => {
                const obj = down(e, 'app');
                document.ontouchmove = (e) => {
                    move(e, 'app', obj);
                };
                document.ontouchend = () => {
                    document.ontouchmove = null;
                    document.ontouchend = null;
                };
            };
        },
    })
    /**
     * 拖动指令2 全局拖动
     */
    app.directive('drags', {
        mounted(el: HTMLElement, binding: DirectiveBinding<any>) {
            let startclientX: number | null = 0; //记录开始的横坐标位置
            let startclientY: number | null = 0; //记录开始的纵坐标位置
            let elRight: number | null = 5; //定位-初始位置
            let elBottom: number | null = 500; //定位-初始位置
            let ballStationS: Filexd = Local.get('ballStation') || null
            el.style.position = 'fixed'
            if (ballStationS) {
                elRight = ballStationS.right
                elBottom = ballStationS.bottom
            }
            el.style.right = elRight + 'px'
            el.style.bottom = elBottom + 'px'
            el.draggable = true
            el.ondragstart = (e) => {
                startclientX = e.clientX;
                startclientY = e.clientY;
            }
            el.ondragend = (e) => {
                // console.log("eeeeee", e);
                let x = startclientX! - e.clientX; // 计算偏移量
                let y = startclientY! - e.clientY;
                elRight! += x; // 实现拖拽元素随偏移量移动
                elBottom! += y;
                Local.set('ballStation', { right: elRight, bottom: elBottom })
            }

        }
    })

    /**
     * 波纹效果
     */
    app.directive('waves', (el: HTMLElement, binding: DirectiveBinding) => {
        const { value } = binding
        let color = 'rgba(90, 90, 90, 0.4)'
        const colorArrs = [
            {
                color: 'light',
                rgba: 'rgba(255,255,255,0.4)'
            },
            {
                color: 'red',
                rgba: 'rgba(255,0,0,0.4)'
            },
            {
                color: 'orange',
                rgba: 'rgba(255,165,0,0.4)'
            },
            {
                color: 'purple',
                rgba: 'rgb(128,0,128,0.4)'
            },
            {
                color: 'green',
                rgba: 'rgb(0,128,0,0.4)'
            },
            {
                color: 'teal',
                rgba: 'rgb(0,128,128,0.4)'
            }
        ]
        if (value) {
            const item = colorArrs.find(item => item.color === value)
            color = item ? item.rgba : color
        }
        el.style.position = 'relative'
        el.style.overflow = 'hidden'
        const createRipple = (event: any) => {
            const button = event.currentTarget;
            const circle = document.createElement("span");
            const diameter = Math.max(button.clientWidth, button.clientHeight);
            const radius = diameter / 2;
            circle.style.width = circle.style.height = `${diameter}px`;
            circle.style.left = `${event.clientX - el.getBoundingClientRect().left - radius}px`;
            circle.style.top = `${event.clientY - el.getBoundingClientRect().top - radius}px`;
            circle.style.backgroundColor = color
            circle.classList.add("wave-animation");
            button.appendChild(circle);
            setTimeout(() => {
                const ripple = button.getElementsByClassName("wave-animation")[0];
                ripple.remove()
            }, 800)
        }
        el.addEventListener('click', createRipple)
    })

    /**
     * 光线追踪
     */
    app.directive('tracing', (el: HTMLElement, binding: DirectiveBinding) => {
        const contentDom = el.querySelector('&>*:first-child') as HTMLElement
        if (contentDom) {
            contentDom.style.zIndex = '2'
        }

        // 计算
        const moveTracingDiameter = Math.min(el.clientWidth, el.clientHeight)
        const moveTracingRadius = moveTracingDiameter / 2

        // 创建 dom
        const moveMaskDom = document.createElement('div') as HTMLElement
        const moveTracingDom = document.createElement('div') as HTMLElement

        // 设置 dom 样式
        el.style.position = 'relative'
        moveMaskDom.style.position = 'absolute'
        moveMaskDom.style.left = '0'
        moveMaskDom.style.top = '0'
        moveMaskDom.style.right = '0'
        moveMaskDom.style.bottom = '0'
        moveMaskDom.style.zIndex = '1'
        moveMaskDom.style.overflow = 'hidden'

        moveTracingDom.style.position = 'absolute'
        moveTracingDom.style.width = moveTracingDom.style.height = moveTracingDiameter + 'px'
        moveTracingDom.style.backgroundImage = 'radial-gradient( #EB00FF 0.99%, #0047FF 89.42%)'
        moveTracingDom.style.filter = 'blur(250px)'
        moveTracingDom.style.display = 'none'

        // 设置 dom
        moveMaskDom.appendChild(moveTracingDom)
        el.appendChild(moveMaskDom)

        // 事件处理
        const currentDomEvent = () => {
            moveTracingDom.style.display = 'block'
        }
        const moveTracingMouseMove = (e: MouseEvent) => {
            const left = el.getBoundingClientRect().left
            const top = el.getBoundingClientRect().top
            moveTracingDom.style.left = e.clientX - left - moveTracingRadius + 'px'
            moveTracingDom.style.top = e.clientY - top - moveTracingRadius + 'px'
        }

        // 绑定事件
        el.addEventListener('mousemove', Debounce(moveTracingMouseMove, 2))
        el.addEventListener('mouseenter', currentDomEvent)
        el.addEventListener('mouseleave', () => {
            moveTracingDom.style.display = 'none'
        })
    })
}
